convert tpo formats to Format class (#1225)
authortsteven4 <13596209+tsteven4@users.noreply.github.com>
Sat, 18 Nov 2023 13:59:38 +0000 (06:59 -0700)
committerGitHub <noreply@github.com>
Sat, 18 Nov 2023 13:59:38 +0000 (06:59 -0700)
* convert tpo to Format class.

* capture comments

CMakeLists.txt
tpo.cc
tpo.h [new file with mode: 0644]
vecs.cc

index 995f6b72499aeef58375799b73f31f557ff80273..9e4a6ee5e194823c9c81d3d614ff30eb0b4536b9 100644 (file)
@@ -237,6 +237,7 @@ set(HEADERS
   skytraq.h
   subrip.h
   text.h
+  tpo.h
   unicsv.h
   units.h
   vcf.h
diff --git a/tpo.cc b/tpo.cc
index dd5a7ab7b6a877e168645097c96bb88601550d3f..d15b1a5124fa45e2cd539975221caf0254c3baf3 100644 (file)
--- a/tpo.cc
+++ b/tpo.cc
     3.x     "recreation"
 */
 
-#include <cmath>                // for abs
+#include "tpo.h"
+
 #include <cstdint>              // for uint8_t
 #include <cstdio>               // for printf, SEEK_CUR, SEEK_SET
+#include <cmath>                // for abs
 #include <cstring>              // for strlen, strncmp
 #include <vector>               // for vector
 
 #include <QScopedArrayPointer>  // for QScopedArrayPointer
 #include <QString>              // for QString
 #include <QStringLiteral>       // for qMakeStringPrivate, QStringLiteral
-#include <QVector>              // for QVector
 #include <QtGlobal>             // for qPrintable, Q_UNUSED
 
-#include "defs.h"
-#include "gbfile.h"             // for gbfread, gbfgetc, gbfgetint32, gbfreadbuf, gbfseek, gbfgetdbl, gbfgetint16, gbfclose, gbfgetnativecstr, gbfgetuint16, gbfopen_le, gbfile
+#include "defs.h"               // for Waypoint, fatal, route_head, le_read32, waypt_add, track_add_wpt, track_add_head, xfree, xmalloc, doing_rtes, doing_wpts, gb_color, route_add_head, route_add_wpt, unknown_alt, doing_trks
+#include "gbfile.h"             // for gbfread, gbfgetc, gbfgetint32, gbfreadbuf, gbfseek, gbfgetdbl, gbfgetint16, gbfclose, gbfgetnativecstr, gbfgetuint16, gbfopen_le
 #include "jeeps/gpsmath.h"      // for GPS_Math_Known_Datum_To_WGS84_M
 
 
 #define MYNAME "TPO"
 
-static char* dumpheader = nullptr;
-
-static
-QVector<arglist_t> tpo2_args = {
-};
-
-static
-QVector<arglist_t> tpo3_args = {
-};
-
-
-static gbfile* tpo_file_in;
-static double track_length;
 
 /*******************************************************************************/
 /*                                      READ                                   */
 /*******************************************************************************/
 
-/* Define a global here that we can query from multiple places */
-static float tpo_version = 0.0;
-
 /* tpo_check_version_string()
    Check the first bytes of the file for a version 3.0 header. */
-static void
-tpo_check_version_string()
+void
+TpoFormatBase::tpo_check_version_string()
 {
 
   unsigned char string_size;
@@ -142,11 +127,11 @@ tpo_check_version_string()
   }
 }
 
-static void
 /* tpo_dump_header_bytes(int header_size)
    Write the first header_size bytes of the file to standard output
    as a C array definition. */
-tpo_dump_header_bytes(int header_size)
+void
+TpoFormatBase::tpo_dump_header_bytes(int header_size)
 {
   QByteArray buffer = gbfreadbuf(header_size, tpo_file_in);
 
@@ -172,8 +157,8 @@ tpo_dump_header_bytes(int header_size)
    Keep reading bytes from the file until the section name is encountered,
    then go seek_bytes forwards (+) or backwards (-) to the start of
    the section data. */
-static void
-tpo_read_until_section(const char* section_name, int seek_bytes)
+void
+TpoFormatBase::tpo_read_until_section(const char* section_name, int seek_bytes)
 {
   char byte;
   unsigned int match_index = 0;
@@ -220,7 +205,7 @@ tpo_read_until_section(const char* section_name, int seek_bytes)
 // that is the only type of data available in the version 2.x TPO
 // files.
 //
-static void tpo_read_2_x()
+void TpoFormatBase::tpo_read_2_x()
 {
   char buff[16];
 
@@ -335,7 +320,7 @@ static void tpo_read_2_x()
 //
 // For version 3.x files.
 //
-static int tpo_read_int()
+int TpoFormatBase::tpo_read_int()
 {
   constexpr int debug = 0;
 
@@ -381,7 +366,7 @@ static int tpo_read_int()
 //
 // For version 3.x/4.x files.
 //
-static int tpo_find_block(unsigned int block_desired)
+int TpoFormatBase::tpo_find_block(unsigned int block_desired)
 {
   unsigned int block_type;
   constexpr int debug = 0;
@@ -419,7 +404,7 @@ static int tpo_find_block(unsigned int block_desired)
 //
 // For version 3.x files.
 //
-static Waypoint* tpo_convert_ll(int lat, int lon)
+Waypoint* TpoFormatBase::tpo_convert_ll(int lat, int lon)
 {
   auto* waypoint_temp = new Waypoint;
 
@@ -453,19 +438,9 @@ static Waypoint* tpo_convert_ll(int lat, int lon)
   return (waypoint_temp);
 }
 
-#define TRACKNAMELENGTH 255
-class StyleInfo
-{
-public:
-  QString name;
-  uint8_t color[3] {0, 0, 0}; // keep R/G/B values separate because line_color needs BGR
-  uint8_t wide{0};
-  uint8_t dash{0};
-};
-
 // Track decoder for version 3.x/4.x files.
 // This block contains tracks (called "freehand routes" in Topo).
-static void tpo_process_tracks()
+void TpoFormatBase::tpo_process_tracks()
 {
   constexpr int debug = 0; // 0-4 for increasingly verbose output in this subroutine)
 
@@ -611,7 +586,7 @@ static void tpo_process_tracks()
     track_style -= 1;  // STARTS AT 1, whereas style arrays start at 0
 
     // Can be 8/16/32-bit value - never used? length in meters?
-    track_length = tpo_read_int();
+    double track_length = tpo_read_int();
 
 //UNKNOWN DATA LENGTH
     unsigned int name_length = tpo_read_int();
@@ -1039,17 +1014,9 @@ static void tpo_process_tracks()
 } // end of tpo_process_tracks
 
 
-// Global index to waypoints, needed for routes, filled in by
-// tpo_process_waypoints.
-//
-// For version 3.x files.
-//
-static Waypoint** tpo_wp_index;
-static unsigned int tpo_index_ptr;
-
 // Waypoint decoder for version 3.x files.
 //
-static void tpo_process_waypoints()
+void TpoFormatBase::tpo_process_waypoints()
 {
   //printf("Processing Waypoints...\n");
 
@@ -1157,7 +1124,7 @@ static void tpo_process_waypoints()
 
 // Map Notes decoder for version 3.x files.
 //
-static void tpo_process_map_notes()
+void TpoFormatBase::tpo_process_map_notes()
 {
   //printf("Processing Map Notes...\n");
 
@@ -1255,7 +1222,7 @@ static void tpo_process_map_notes()
 
 // Symbols decoder for version 3.x files.
 //
-static void tpo_process_symbols()
+void TpoFormatBase::tpo_process_symbols()
 {
   //printf("Processing Symbols...\n");
 
@@ -1298,7 +1265,7 @@ static void tpo_process_symbols()
 
 // Text Labels decoder for version 3.x files.
 //
-static void tpo_process_text_labels()
+void TpoFormatBase::tpo_process_text_labels()
 {
   //printf("Processing Text Labels...\n");
 
@@ -1362,7 +1329,7 @@ static void tpo_process_text_labels()
 // with pointers to waypoint objects by tpo_process_waypoints()
 // function above.
 //
-static void tpo_process_routes()
+void TpoFormatBase::tpo_process_routes()
 {
   //printf("Processing Routes...\n");
 
@@ -1446,7 +1413,7 @@ static void tpo_process_routes()
 #ifdef DEAD_CODE_IS_REBORN
 // Compass decoder for version 3.x files.
 //
-static void tpo_process_compass()
+void TpoFormatBase::tpo_process_compass()
 {
 
   // Not implemented yet
@@ -1461,7 +1428,7 @@ static void tpo_process_compass()
 // (called "freehand routes" or just "routes" in Topo), "waypoints",
 // and "gps-routes".  We intend to read all three types.
 //
-static void tpo_read_3_x()
+void TpoFormatBase::tpo_read_3_x()
 {
 
   if (doing_trks) {
@@ -1517,8 +1484,8 @@ static void tpo_read_3_x()
 
 
 
-static void
-tpo_rd_init(const QString& fname)
+void
+TpoFormatBase::tpo_rd_init(const QString& fname)
 {
 
   // prepare for an attempt to deallocate memory that may or may not get allocated
@@ -1547,8 +1514,8 @@ tpo_rd_init(const QString& fname)
   }
 }
 
-static void
-tpo_rd_deinit()
+void
+TpoFormatBase::tpo_rd_deinit()
 {
   // Free the waypoint index, we don't need it anymore.
   for (unsigned int i = 0; i < tpo_index_ptr; i++) {
@@ -1565,8 +1532,8 @@ tpo_rd_deinit()
   gbfclose(tpo_file_in);
 }
 
-static void
-tpo_read()
+void
+TpoFormatBase::tpo_read()
 {
 
   if (tpo_version == 2.0) {
@@ -1579,33 +1546,3 @@ tpo_read()
     fatal(MYNAME ": gpsbabel can only read TPO versions through 3.x.x\n");
   }
 }
-
-/* TPO 2.x format can read tracks only */
-ff_vecs_t tpo2_vecs = {
-  ff_type_file,   /* ff_type_internal */
-  { ff_cap_none, ff_cap_read,  ff_cap_none },
-  tpo_rd_init,
-  nullptr,
-  tpo_rd_deinit,
-  nullptr,
-  tpo_read,
-  nullptr,
-  nullptr,
-  &tpo2_args,
-  NULL_POS_OPS
-};
-
-/* TPO 3.x format can read waypoints/tracks/routes */
-ff_vecs_t tpo3_vecs = {
-  ff_type_file,   /* ff_type_internal */
-  { ff_cap_read, ff_cap_read, ff_cap_read },
-  tpo_rd_init,
-  nullptr,
-  tpo_rd_deinit,
-  nullptr,
-  tpo_read,
-  nullptr,
-  nullptr,
-  &tpo3_args,
-  NULL_POS_OPS
-};
diff --git a/tpo.h b/tpo.h
new file mode 100644 (file)
index 0000000..43a0c7e
--- /dev/null
+++ b/tpo.h
@@ -0,0 +1,213 @@
+/*
+    National Geographic Topo! TPO file support.
+    2.x support contributed to gpsbabel by Steve Chamberlin.
+    3.x support contributed to gpsbabel by Curt Mills.
+    4.x files read properly when treated as 3.x (final release was 4.5)
+    track parsing bugs fixed by Steve Eckert in 2012 and 2020
+
+    Topo! version 2.x:      Tracks are implemented.
+    Topo! version 3.x/4.x:  Reading of Tracks/Waypoints/Routes is
+                            implemented.  Also extracts Map Notes/
+                            Symbols/Text Labels as Waypoints.
+
+    Copyright (C) 2005 Steve Chamberlin, slc at alum.mit.edu
+    Portions Copyright (C) 2006 Curtis E. Mills, archer at eskimo dot com
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ */
+
+/*
+ TPO format notes:
+ -----------------
+ Most of the ASCII strings embedded in the text will have a
+ byte-count prepended to the string.  Unknown yet whether other
+ fields have this same byte-count, but so far it doesn't look like
+ it.
+
+ New format (3.x and later) files begin with a string byte-count
+ byte and then a string starting with "TOPO! Ver. 3.", like "TOPO!
+ Ver.  3.3.4".  Can contain routes/tracks/waypoints, embedded
+ images, Map Notes, Symbols, Text Labels, Compass symbols, and
+ several others.
+
+ Older (pre-3.0) format does not have the above string.  Contains
+ only tracks.  Waypoints are saved in a separate .TPG file.
+
+ Track parsing has been problematic and may still not be right!
+ See further notes and clues in tpo_process_tracks()
+ (can #define Tracks2012 to revert to pre-2020 code in tpo_process_tracks)
+
+ May contain these strings:
+    Frmt:   String:
+    -----   --------------------------------
+    2.x     "CTopoAzimuth"
+    2.x     "CTopoBookmark"
+    2.x     "CTopoGpsRoute".  Saved in .tpg files (see tpg.c)
+    2.x     "CTopoRoute".  The actual tracks we parse here.
+    2.x     "CTopoSymbol"
+    2.x/3.x "CTopoText"
+    2.x     "CTopoWaypoint".  Saved in .tpg files (see tpg.c)
+    3.x     "Notes"
+    3.x     "PNG."  Embedded PNG image containing 2 rows of 40
+              symbols each.  Starts with signature: 89 50 4e 47 0d
+              0a 1a 0a, ends with signature 49 45 4e 44 ae 42 60 82.
+    3.x     "shapes"
+    3.x     "arrows"
+    3.x     "recreation"
+*/
+#ifndef TPO_H_INCLUDED_
+#define TPO_H_INCLUDED_
+
+#include <QString>   // for QString
+#include <QVector>   // for QVector
+#include <cstdint>   // for uint8_t
+#include "defs.h"    // for ff_cap, arglist_t, ff_cap_none, ff_cap_read, Waypoint, ff_type, ff_type_file
+#include "format.h"  // for Format
+#include "gbfile.h"  // for gbfile
+
+
+class TpoFormatBase
+{
+protected:
+  /* Constants */
+
+  static constexpr int TRACKNAMELENGTH = 255;
+
+  /* Types */
+
+  class StyleInfo
+  {
+  public:
+    QString name;
+    uint8_t color[3] {0, 0, 0}; // keep R/G/B values separate because line_color needs BGR
+    uint8_t wide{0};
+    uint8_t dash{0};
+  };
+
+  /* Member Functions */
+
+  void tpo_check_version_string();
+  void tpo_dump_header_bytes(int header_size);
+  void tpo_read_until_section(const char* section_name, int seek_bytes);
+  void tpo_read_2_x();
+  int tpo_read_int();
+  int tpo_find_block(unsigned int block_desired);
+  static Waypoint* tpo_convert_ll(int lat, int lon);
+  void tpo_process_tracks();
+  void tpo_process_waypoints();
+  void tpo_process_map_notes();
+  void tpo_process_symbols();
+  void tpo_process_text_labels();
+  void tpo_process_routes();
+  void tpo_read_3_x();
+  void tpo_rd_init(const QString& fname);
+  void tpo_rd_deinit();
+  void tpo_read();
+
+  /* Data Members */
+
+  char* dumpheader = nullptr;
+  gbfile* tpo_file_in{};
+
+  // Define a global here that we can query from multiple places.
+  float tpo_version = 0.0;
+
+  // Global index to waypoints, needed for routes, filled in by
+  // tpo_process_waypoints.
+  //
+  // For version 3.x files.
+  Waypoint** tpo_wp_index{};
+  unsigned int tpo_index_ptr{};
+};
+
+class Tpo2Format : public Format, private TpoFormatBase
+{
+public:
+  QVector<arglist_t>* get_args() override
+  {
+    return &tpo2_args;
+  }
+
+  ff_type get_type() const override
+  {
+    return ff_type_file;
+  }
+
+  QVector<ff_cap> get_cap() const override
+  {
+    /* TPO 2.x format can read tracks only */
+    /*         waypoints,      tracks,      routes */
+    return { ff_cap_none, ff_cap_read,  ff_cap_none };
+  }
+
+  void rd_init(const QString& fname) override
+  {
+    tpo_rd_init(fname);
+  }
+  void read() override
+  {
+    tpo_read();
+  }
+  void rd_deinit() override
+  {
+    tpo_rd_deinit();
+  }
+
+private:
+  /* Data Members */
+
+  QVector<arglist_t> tpo2_args = {};
+};
+
+class Tpo3Format : public Format, private TpoFormatBase
+{
+public:
+  QVector<arglist_t>* get_args() override
+  {
+    return &tpo3_args;
+  }
+
+  ff_type get_type() const override
+  {
+    return ff_type_file;
+  }
+
+  QVector<ff_cap> get_cap() const override
+  {
+    /* TPO 3.x format can read waypoints/tracks/routes */
+    /*         waypoints,      tracks,      routes */
+    return { ff_cap_read, ff_cap_read, ff_cap_read };
+  }
+
+  void rd_init(const QString& fname) override
+  {
+    tpo_rd_init(fname);
+  }
+  void read() override
+  {
+    tpo_read();
+  }
+  void rd_deinit() override
+  {
+    tpo_rd_deinit();
+  }
+
+private:
+  /* Data Members */
+
+  QVector<arglist_t> tpo3_args = {};
+};
+#endif // TPO_H_INCLUDED_
diff --git a/vecs.cc b/vecs.cc
index f35289088a84b575614122ca85cf3dd0e371b2af..41b5c6943ca25eaa654886fe6c8eeb6ed7c01b62 100644 (file)
--- a/vecs.cc
+++ b/vecs.cc
@@ -69,6 +69,7 @@
 #include "src/core/logging.h"  // for Warning, FatalMsg
 #include "subrip.h"            // for SubripFormat
 #include "text.h"              // for TextFormat
+#include "tpo.h"               // for Tpo2Format, Tpo3Format
 #include "unicsv.h"            // for UnicsvFormat
 #include "vcf.h"               // for VcfFormat
 #include "xcsv.h"              // for XcsvStyle, XcsvFormat
@@ -79,8 +80,6 @@ extern ff_vecs_t geo_vecs;
 extern ff_vecs_t ozi_vecs;
 #if MAXIMAL_ENABLED
 extern ff_vecs_t tpg_vecs;
-extern ff_vecs_t tpo2_vecs;
-extern ff_vecs_t tpo3_vecs;
 extern ff_vecs_t gpl_vecs;
 extern ff_vecs_t mtk_vecs;
 extern ff_vecs_t mtk_fvecs;
@@ -123,8 +122,8 @@ struct Vecs::Impl {
 #if MAXIMAL_ENABLED
   LowranceusrFormat lowranceusr_fmt;
   LegacyFormat tpg_fmt {tpg_vecs};
-  LegacyFormat tpo2_fmt {tpo2_vecs};
-  LegacyFormat tpo3_fmt {tpo3_vecs};
+  Tpo2Format tpo2_fmt;
+  Tpo3Format tpo3_fmt;
 #if SHAPELIB_ENABLED
   ShapeFormat shape_fmt;
 #endif